﻿using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

namespace XFFSM
{
    public class FSMEditorWindow : EditorWindow
    {

        #region 字段

        private Rect paramArea; // 参数区域

        private Rect stateArea; // 状态区域

        private float percent_of_param = 0.4f; // 参数所占用的比例

        private Rect paramResizeArea;

        const float ResizeWidth = 10f;

        private bool isResizingParamArea = false; // 是否正在调整参数区域

        private List<GraphLayer> graphLayers = new List<GraphLayer>();

        private ParamLayer paramLayer;

        #endregion

        #region 属性
        public Context Context { get; private set; } = new Context();

        #endregion


        #region 生命周期
        private void Update()
        {
            Repaint();

            if (graphLayers != null)
            {
                foreach (var item in graphLayers)
                {
                    item.Update();
                }
            }

        }
        private void OnGUI()
        {
            
            paramArea.Set(0, 0, this.position.width * percent_of_param /*- ResizeWidth / 2*/, this.position.height);
            stateArea.Set(paramArea.width /*+ ResizeWidth*/, 0, this.position.width * (1 - percent_of_param) /*- ResizeWidth / 2*/, this.position.height);

            ParamAreaResize();

            if (graphLayers.Count == 0) {
                InitLayers();
            }

            foreach (var item in graphLayers)
            {
                item.OnGUI(stateArea);
            }

            if (IsProcessEventOnStateArea())
            {

                for (int i = graphLayers.Count - 1; i >= 0; i--)
                {
                    graphLayers[i].ProcessEvents();
                }
            }

            if (paramLayer == null) {
                paramLayer = new ParamLayer(this);
            }

            paramLayer.OnGUI(paramArea);
            paramLayer.ProcessEvents();

        }


        private void OnEnable()
        {
            wantsMouseEnterLeaveWindow = true;
        }

        private void OnLostFocus()
        {

            if (graphLayers != null)
            {
                foreach (var item in graphLayers)
                {
                    item.OnLostFocus();
                }
            }

            if (paramLayer!=null) { 
                paramLayer.OnLostFocus();
            }


        }

        #endregion


        #region 方法

        [MenuItem("Assets/Create/XFFSM/State Machine Window")]
        static void OpenWindow() {
            GetWindow<FSMEditorWindow>().Show();
        }


        // 调整参数区域
        private void ParamAreaResize() {
            paramResizeArea.Set(paramArea.width - ResizeWidth / 2, 0, ResizeWidth, position.height);

            EditorGUIUtility.AddCursorRect(paramResizeArea, MouseCursor.ResizeHorizontal);

            if ( Event.current.type == EventType.MouseDown && paramResizeArea.Contains(Event.current.mousePosition)) {
                isResizingParamArea = true;
                Event.current.Use();
            }

            if ( isResizingParamArea ) {
                percent_of_param = Mathf.Clamp(  Event.current.mousePosition.x / position.width,0.1f,0.5f);
                //Event.current.Use();
            }

            if (Event.current.type == EventType.MouseUp  ) {
                isResizingParamArea = false;
                if (paramResizeArea.Contains(Event.current.mousePosition)) { 
                    Event.current.Use();
                }
            }

        }

        private void InitLayers() {
            graphLayers.Add(new BackgroundLayer(this));
            graphLayers.Add(new TransitionLayer(this));
            graphLayers.Add(new StateNodeLayer(this));
        }

        public bool IsProcessEventOnStateArea() {
            bool mousePosition = stateArea.Contains(Event.current.mousePosition);
            bool isMouseUp = (Event.current.type == EventType.MouseUp && Event.current.button == 0 );
            bool isMouseLeave = Event.current.type == EventType.MouseLeaveWindow;
            return mousePosition || isMouseUp || isMouseLeave;
        }

        #endregion

    }
}


